package com.manager.controller

import com.base.model.admin_api.Model_AdminAPI
import com.google.code.kaptcha.impl.DefaultKaptcha
import com.manager.config.IFinal
import com.manager.config.IJkid
import com.manager.rpc.RPC_AdminAPI
import com.yfree.global.YController
import com.yfree.model.YModel
import com.yfree.utils.YMD5Utils
import io.seata.spring.annotation.GlobalTransactional
import org.apache.shiro.SecurityUtils
import org.apache.shiro.authc.UsernamePasswordToken
import org.springframework.cloud.context.config.annotation.RefreshScope
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestMethod
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.multipart.MultipartFile
import org.springframework.web.servlet.ModelAndView
import java.io.ByteArrayOutputStream
import java.io.File
import javax.imageio.ImageIO
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse

@RefreshScope
@Controller
class Controller_Manager(
    val defaultKaptcha: DefaultKaptcha,
    val rpc_AdminAPI: RPC_AdminAPI
) : YController() {
    fun <T : YModel> callAdminAPI(jkid: String, hashMap: Map<String, Any> = mapOf(), clazz: Class<T>, throwWhenUnSuccess: Boolean = true) = yFromRPC(rpc_AdminAPI.`interface`(jkid, gson.toJson(hashMap)), clazz, "${jkid}调用失败", throwWhenFail = throwWhenUnSuccess)
    fun callAdminAPI(jkid: String, hashMap: Map<String, Any> = mapOf(), throwWhenUnSuccess: Boolean = true) = yFromRPC(rpc_AdminAPI.`interface`(jkid, gson.toJson(hashMap)), "${jkid}调用失败", throwWhenUnSuccess = throwWhenUnSuccess)

    val codeSessionKey = "rightCode"

    @GlobalTransactional
    @RequestMapping("/", method = [RequestMethod.GET])
    fun index(message: String?, request: HttpServletRequest): ModelAndView {
        val username = request.session.getAttribute("username")
        val password = request.session.getAttribute("password")
        return if (username == null || password == null)
            ModelAndView(
                IFinal.Page.登录页.rawValue, mapOf(
                    "message" to (message ?: "请登录")
                )
            )
        else {
            val tempCode = "tempCode"
            request.session.setAttribute(codeSessionKey, tempCode)
            main(username.toString(), password.toString(), tempCode, request)
        }
    }

    @GlobalTransactional
    @RequestMapping("/getCode", method = [RequestMethod.GET])
    fun getCode(request: HttpServletRequest, response: HttpServletResponse) {
        val createText = defaultKaptcha.createText()
        request.session.setAttribute(codeSessionKey, createText)
        val jpegOutputStream = ByteArrayOutputStream()
        ImageIO.write(defaultKaptcha.createImage(createText), "jpg", jpegOutputStream)
        response.setHeader("Cache-Control", "no-store")
        response.setHeader("Pragma", "no-cache")
        response.setDateHeader("Expires", 0)
        response.contentType = "image/jpeg"
        response.outputStream.write(jpegOutputStream.toByteArray())
        response.outputStream.flush()
        response.outputStream.close()
    }

    @GlobalTransactional
    @RequestMapping("/main", method = [RequestMethod.POST])
    fun main(username: String, password: String, code: String, request: HttpServletRequest): ModelAndView {
        if (code != request.session.getAttribute(codeSessionKey)) //验证码错误
            return ModelAndView(
                "redirect:/", mapOf(
                    "message" to "验证码错误"
                )
            )
        val result = callAdminAPI(
            IJkid.用户.登录.rawValue, mapOf(
                "username" to username,
                "password" to password
            ), Model_AdminAPI::class.java, false
        )
        val model = result.root.result.firstOrNull() ?: return ModelAndView(
            "redirect:/", mapOf(
                "message" to "用户名或密码错误"
            )
        )
        request.session.setAttribute("username", username)
        request.session.setAttribute("password", password)
        return ModelAndView(
            IFinal.Page.主页.rawValue, mapOf(
                "userList" to model.userList,
                "sex" to model.sex
            )
        )
    }

    @GlobalTransactional
    @RequestMapping("/logout", method = [RequestMethod.POST])
    fun logout(request: HttpServletRequest): ModelAndView {
        request.session.removeAttribute("username")
        request.session.removeAttribute("password")
        return ModelAndView("redirect:/")
    }

    @GlobalTransactional
    @RequestMapping("/uploadFile", method = [RequestMethod.POST])
    fun uploadFile(@RequestParam(value = "file") files: List<MultipartFile>): ModelAndView {
        files.forEach { file ->
            val dest = File("/Users/ymac/Desktop/static/imgs")
            if (!dest.exists()) dest.mkdirs()
            file.transferTo(File(dest, "${System.currentTimeMillis()}.${file.originalFilename!!.split(".").last()}"))
        }
        return ModelAndView("redirect:/")
    }

    @GlobalTransactional
    @RequestMapping("/shiro_anon", method = [RequestMethod.GET])
    fun shiro_anon(): ModelAndView {
        return ModelAndView(
            IFinal.Page.ShiroSuccess.rawValue, mapOf(
                "name" to "shiro_anon"
            )
        )
    }

    @GlobalTransactional
    @RequestMapping("/shiro_authc", method = [RequestMethod.GET])
    fun shiro_authc(): ModelAndView {
        return ModelAndView(
            IFinal.Page.ShiroSuccess.rawValue, mapOf(
                "name" to "shiro_authc"
            )
        )
    }

    @GlobalTransactional
    @RequestMapping("/shiro_authcBasic", method = [RequestMethod.GET])
    fun shiro_authcBasic(): ModelAndView {
        return ModelAndView(
            IFinal.Page.ShiroSuccess.rawValue, mapOf(
                "name" to "shiro_authcBasic"
            )
        )
    }

    @GlobalTransactional
    @RequestMapping("/shiro_login", method = [RequestMethod.GET])
    fun shiro_login(message: String?): ModelAndView {
        return ModelAndView(
            IFinal.Page.ShiroLogin.rawValue, mapOf(
                "message" to (message ?: "请登录")
            )
        )
    }

    @GlobalTransactional
    @RequestMapping("/shiro_unauthorized", method = [RequestMethod.GET])
    fun shiro_unauthorized(message: String?): ModelAndView {
        return ModelAndView(IFinal.Page.ShiroUnauthorized.rawValue)
    }

    @GlobalTransactional
    @RequestMapping("/shiro_check", method = [RequestMethod.POST])
    fun shiro_check(username: String, password: String): ModelAndView {
        return try {
            SecurityUtils.getSubject().login(UsernamePasswordToken(username, YMD5Utils.getMD5(password)))
            ModelAndView(
                IFinal.Page.ShiroSuccess.rawValue, mapOf(
                    "name" to "shiro_check"
                )
            )
        } catch (e: Exception) {
            ModelAndView(
                IFinal.Page.ShiroLogin.rawValue, mapOf(
                    "message" to "用户名或密码错误：${e.localizedMessage}"
                )
            )
        }
    }

    @GlobalTransactional
    @RequestMapping("/shiro_yfree1/role", method = [RequestMethod.GET])
    fun shiro_yfree1(): ModelAndView {
        return ModelAndView(IFinal.Page.ShiroSuccess_YFree1.rawValue)
    }

    @GlobalTransactional
    @RequestMapping("/shiro_yfree2/role", method = [RequestMethod.GET])
    fun shiro_yfree2(): ModelAndView {
        return ModelAndView(IFinal.Page.ShiroSuccess_YFree2.rawValue)
    }
}
